<!DOCTYPE html>
<html>

    <head>
		<meta charset="utf-8" />
		<title>FlipIt</title>
	</head>
	<style>
		* {
			margin: 0;
			padding: 0;
		}
		.canvas {
			font-size: 0;
			-webkit-text-size-adjust: none;
		}
		.canvas div {
			display: inline-block;
			border-radius: 3px;
			cursor: pointer;
			margin: 1px;
		}
		.border1 {
			border: 2px solid #D00 !important;
			transition: all .5s;
		}
		.border2 {
			border: 2px solid #0D0 !important;
			transition: all .5s ease 0s;
		}
		.border3 {
			border: 2px solid #D0D !important;
			transition: all .5s ease 0s;
		}
		.tile1 {
			border: 2px solid #444;
			background-color: rgb(230, 171, 94);
			animation: flip1 .8s ease;
		}
		.tileEnd1 {
			border: 2px solid #444;
			background-color: rgb(107, 155, 244);
		}
		@keyframes flip1 {
			1% {
				background-color: rgb(230, 171, 94)
			}
			49% {
				transform: rotate3d(-1, 1, 0, -90deg);
				background-color: rgb(230, 171, 94)
			}
			50% {
				transform: rotate3d(-1, 1, 0, -90deg);
				background-color: rgb(107, 155, 244)
			}
			100% {
				transform: rotate3d(-1, 1, 0, -180deg);
				background-color: rgb(107, 155, 244);
			}
		}
		.tileEnd1:hover {
			border: 2px solid #888;
			background-color: rgb(127, 175, 254);
			transition: all .5s ease 0s;
		}
		.tile2 {
			border: 2px solid #444;
			background-color: rgb(107, 155, 244);
			animation: flip2 .8s ease;
		}
		.tileEnd2 {
			border: 2px solid #444;
			background-color: rgb(230, 171, 94);
		}
		@keyframes flip2 {
			1% {
				background-color: rgb(107, 155, 244)
			}
			49% {
				transform: rotate3d(-1, 1, 0, -90deg);
				background-color: rgb(107, 155, 244)
			}
			50% {
				transform: rotate3d(-1, 1, 0, -90deg);
				background-color: rgb(230, 171, 94)
			}
			100% {
				transform: rotate3d(-1, 1, 0, -180deg);
				background-color: rgb(230, 171, 94);
			}
		}
		.tile2:hover {
			border: 2px solid #888;
			background-color: rgb(250, 175, 114);
			transition: all .5s ease 0s;
		}
	</style>

	<body>
		<div style="max-width: 1000px;margin: 10px auto;">
			<div class="canvas" style="width: 600px;height: 600px;margin: 10px auto;border:1px solid #000;padding:10px;">
			</div>
		</div>
	</body>
	<script type="text/javascript">
		var addClass = function(e, c) {
			e.className += " " + c;
			return e;
		}
		var haveClass = function(e, c) {
			return e && e.className.indexOf(c) >= 0;
		}
		var removeClass = function(e, c) {
			if (e && e.className) {
				e.className = e.className.replace(new RegExp(" " + c, "g"), "");
				if (e.className.indexOf(c) == 0) {
					e.className = e.className.substring(c.length + 1, e.className.length);
				}
			}
			return e;
		}
		var random = function(n, m) {
			if (m && n > m) {
				var t = {},
					ret = [];
				while (1) {
					var r = random(n);
					if (!t[r]) {
						ret.push(r);
						t[r] = true;
						if (ret.length == m) break;
					}
				}
				return ret.sort();
			}
			return Math.round(Math.random() * (n - 1));
		}
		var getAll = function(o) {
			return o.getElementsByTagName("div");
		}
		var get = function(o, i) {
			return getAll(o)[i];
		}
		var init = function() {
			var n = document.getElementById("n") && document.getElementById("n").value;
			n = n || 5;
			var c = document.getElementsByClassName("canvas")[0];
			var w = c.style.width;
			w = w.substr(0, w.length - 2);
			w = (w - 22) / n - 2;
			var e = document.createElement("div");
			addClass(e, "tile1")
			e.style.height = w + "px";
			e.style.width = w + "px";
			for (var i = n * n; i > 0; i--) {
				c.appendChild(e.cloneNode());
			}
			return {
				c: c,
				n: n
			};
		}
		var hit0 = function(n, i) {
			n = +n;
			i = +i;
			var b = i - i % n,
				c = b + n,
				u = i - n,
				d = i + n,
				l = i - 1,
				r = i + 1;
			u = u >= 0 ? u : -1;
			d = d < n * n ? d : -1;
			l = l >= b ? l : -1;
			r = r < c ? r : -1;
			return [u, d, l, r];
		}
		var hit = function(a, n, i) {
			var m = hit0(n, i)
			a[m[0]] = !a[m[0]];
			a[m[1]] = !a[m[1]];
			a[m[2]] = !a[m[2]];
			a[m[3]] = !a[m[3]];
			a[i] = !a[i];
			return a;
		}
		var toggle = function(e) {
			if (!e) return;
			if (haveClass(e, "tile1")) {
				removeClass(e, "tile1");
				addClass(e, "tile2");
			} else {
				removeClass(e, "tile2");
				addClass(e, "tile1");
			}
		}
		var play = function(c, n, i) {
			var a = getAll(c);
			var m = hit0(n, i);
			toggle(a[m[0]]);
			toggle(a[m[1]]);
			toggle(a[m[2]]);
			toggle(a[m[3]]);
			toggle(a[i]);
			return a;
		}
		var plus = function(a, n) {
			for (var i = 0; i < n; i++) {
				a[i] = !a[i];
				if (a[i]) break;
			}
			if (i == n) return false;
			return a;
		}
		var check = function(a) {
			for (var i = 0; i < a.length; i++) {
				if (a[i]) return true;
			}
			return false;
		}
		var show1 = function(r, c) {
			for (var ran in r) {
				removeClass(get(c, r[ran]), "tile1");
				addClass(get(c, r[ran]), "tile2");
			}
		}
		var show2 = function(a, c) {
			for (var i in a) {
				if (a[i]) addClass(get(c, i), "border2");
			}
		}
		var solve = function(r, o) {
			var a = [],
				counter = [],
				n = o.n,
				l = n * n - 1;
			for (var i = l; i >= 0; i--) {
				a[i] = false;
			}
			for (var ran in r) {
				a[r[ran]] = true;
			}
			var fn = function() {
				var temp = [];
				for (var i in a) {
					temp[i] = a[i];
				}
				if (plus(counter, n)) {
					for (var i = 0; i < n; i++) {
						if (counter[i]) hit(temp, n, i);
					}
					for (var i = n; i <= l; i++) {
						if (temp[i - n]) {
							hit(temp, n, i);
						}
					}
					if (!check(temp)) {
						alert(counter);
					} else {
						console.warn(counter);
						console.log(temp)
					}
					fn();
				} else {
					console.log(0);
				}
			}
			fn();
		}
		var o = init();
		var r = random(o.n * o.n, 2);
		console.log(r);
		show1(r, o.c);
		o.c.onclick = function() {
			var e = arguments[0].target;
			var f = getAll(this);
			for (var t in f) {
				if (f[t] == e) {
					play(this, o.n, t);
				}
			}
		};
		o.c.addEventListener("animationend", function() { //动画结束时事件 
			var e = arguments[0].target;
			e.className = e.className.replace(/tileEnd\d/, "")
					.replace('tile1', 'tile1 tileEnd1')
					.replace('tile2', 'tile2 tileEnd2');
		}, false);
		solve(r, o, true);
	</script>

</html>